// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

#include "devicefinder.h"
#include "devicehandler.h"
#include "deviceinfo.h"
#include "heartrate-global.h"

#include <QFile>

DeviceFinder::DeviceFinder(DeviceHandler *handler, QObject *parent):
    BluetoothBaseClass(parent),
    m_deviceHandler(handler)
{
    //! [devicediscovery-1]
    m_deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
    m_deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(15000);

    connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &DeviceFinder::addDevice);
    connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::errorOccurred, this,
            &DeviceFinder::scanError);

    connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &DeviceFinder::scanFinished);
    connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled, this, &DeviceFinder::scanFinished);
    //! [devicediscovery-1]

    connect(this, &DeviceFinder::bin_nameChanged, this, &DeviceFinder::onBin_nameChanged);

    if (simulator) {
        m_demoTimer.setSingleShot(true);
        m_demoTimer.setInterval(2000);
        connect(&m_demoTimer, &QTimer::timeout, this, &DeviceFinder::scanFinished);
    }

    bin_dir="/sdcard/DT45G";
    bin_name="";

    LOGD("deviceFinder construct");
}

DeviceFinder::~DeviceFinder()
{
    qDeleteAll(m_devices);
    m_devices.clear();
}

void DeviceFinder::startSearch()
{
    LOGD("\nstart search...");

    clearMessages();
    m_deviceHandler->setDevice(nullptr);
    qDeleteAll(m_devices);
    m_devices.clear();

    emit devicesChanged();  //对外声明是devices（QML可见），内部为m_devices。上面清空了m_devices，发消息后，QML按m_devices新值，更新UI（即设备列表为空）。

    if (simulator) {
        m_demoTimer.start();
    }  else {
        //! [devicediscovery-2]
        m_deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
        //! [devicediscovery-2]
    }

    emit scanningChanged();     //因为已经开启扫描（->start），m_deviceDiscoveryAgent->isActive()已变化，为true，所以发射信号，更新UI中按钮样子。
    setInfo(tr("Scanning for devices..."));
}

//! [devicediscovery-3]
void DeviceFinder::addDevice(const QBluetoothDeviceInfo &device)
{
    //先遍历m_devices是否已经存在。如果不存在，则添加。
//    for (QObject *entry : qAsConst(m_devices)) {
//        auto device = qobject_cast<DeviceInfo *>(entry);
//        if (device && device->getAddress() == address ) {
//            currentDevice = device;
//            break;
//        }
//    }

    // If device is LowEnergy-device, add it to the list
    if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
        m_devices.append(new DeviceInfo(device));
        setInfo(tr("Low Energy device found. Scanning more..."));
//! [devicediscovery-3]
        emit devicesChanged();  //属性devices自带信号。
//! [devicediscovery-4]
    }
    //...
}
//! [devicediscovery-4]

void DeviceFinder::scanError(QBluetoothDeviceDiscoveryAgent::Error error)
{
    if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError)
        setError(tr("The Bluetooth adaptor is powered off."));
    else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError)
        setError(tr("Writing or reading from the device resulted in an error."));
    else
        setError(tr("An unknown error has occurred."));
}

void DeviceFinder::scanFinished()
{
    if (simulator) {
        // Only for testing
        for (int i = 0; i < 4; i++)
            m_devices.append(new DeviceInfo(QBluetoothDeviceInfo()));
    }

    if (m_devices.isEmpty())
        setError(tr("No Low Energy devices found."));
    else
        setInfo(tr("Scanning done."));

    emit scanningChanged();  //扫描完成，->isActive()变为false，要通知UI更新按钮状态。
    emit devicesChanged();
}

void DeviceFinder::onBin_nameChanged()
{
    qDebug()<<"sfdsfjdslf"<<bin_name;
}

/*在列表m_devices中遍历，找到指定地址的device（又包装了一层的QBluetoothDeviceInfo），对该QBluetoothDeviceInfo*进行连接。
*/
void DeviceFinder::connectToService(const QString &address)
{
    m_deviceDiscoveryAgent->stop();

    DeviceInfo *currentDevice = nullptr;
    for (QObject *entry : qAsConst(m_devices)) {
        auto device = qobject_cast<DeviceInfo *>(entry);
        if (device && device->getAddress() == address ) {
            currentDevice = device;
            break;
        }
    }

    if (currentDevice)
        m_deviceHandler->setDevice(currentDevice);      //deviceFinder不处理其他事，所以之后的连接操作由deviceHandler实现。

    clearMessages();
}

void DeviceFinder::openfile(quint32 idx)
{
    if( bin_list.at(idx).isEmpty() ||
        bin_list.at(idx).isNull() ){
        LOGD("file_bin is empty nor NULL");
    }

    QFile file_bin;

    file_bin.setFileName(bin_dir+"/"+bin_list.value(idx));  //这样的操作，bin_dir不必暴露给QML。
    qDebug()<<"file_bin name:"<< file_bin.fileName();

    if(true != file_bin.open(QIODevice::ReadOnly)){
        qDebug()<<"err: bin_file open";
        return;
    }
    else{
        LOGD("open file ok %s", __FUNCTION__);
    }
}

bool DeviceFinder::scanning() const
{
    if (simulator)
        return m_demoTimer.isActive();
    return m_deviceDiscoveryAgent->isActive();
}

QVariant DeviceFinder::devices()
{
    return QVariant::fromValue(m_devices);  //m_devices是QList<QObjects*>，在这里，QVariant::fromValue(const T&value)，返回值是template <typename T>。我是没懂。
}

QVariant DeviceFinder::get_bin_list()
{
    return QVariant::fromValue(bin_list);
}


QString DeviceFinder::get_bin_dir()
{
    return bin_dir;
}

QString DeviceFinder::get_bin_name()
{
    return bin_name;
}

void DeviceFinder::set_bin_name(QString name)
{
    bin_name= name;
}

